import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


// 功能：批量替换 Android 工程中的中文字符串 (xml文件和kt文件)
public class KotlinChineseReplacer {
    // 统一管理所有字符串资源
    private static final Map<String, String> contentToKeyMap = new HashMap<>();//key为中文字符串，value为string资源名
    private static int keyCounter = 1;

    // 需要插入的导入语句 不同项目需要修改 AddInfo   ************
    private static final String IMPORT_R = "import "+AddInfo.packageName+".R";
    private static final String IMPORT_STRING_BY_ID = "import "+AddInfo.packageName+".utils.stringById";
    static String filePath = AddInfo.filePath + "\\res\\values\\strings.xml";// strings.xml文件路径

    private static final Set<Path> modifiedFiles = new HashSet<>();// 标记已修改的文件

    public static void main(String[] args) {
        //不同项目需要修改路径 ****
        Path rootPath = Paths.get(AddInfo.filePath);

        try {
            collectAllStrings(rootPath);//正则表达式收集中文数据

            replaceAllStrings(rootPath);//替换为string资源引用

            insertImportsForModifiedFiles();//为修改过的文件插入导入语句

            System.out.println("\n生成的字符串资源：");
            List<String> stringsToInsert = new ArrayList<>();
            contentToKeyMap.forEach((k, v) -> {
                String str = "<string name=\"" + v + "\">" + k + "</string>";
                System.out.println(str);
                stringsToInsert.add(str);
            });

            XmlListInserter.insertStringsBeforeClosingTag(filePath, stringsToInsert);
            System.out.println("字符串已成功插入到文件中！");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 第一阶段：收集所有需要替换的字符串
    private static void collectAllStrings(Path root) throws IOException {

        Files.walk(root)
                .filter(Files::isRegularFile)
                .filter(p -> {
                    String fileName = p.toString().toLowerCase();
                    return fileName.endsWith(".xml") || fileName.endsWith(".kt");
                })
                .filter(p -> !p.getFileName().toString().equalsIgnoreCase("string.xml"))
                .filter(p -> !p.getFileName().toString().equalsIgnoreCase("themes.xml"))
                .forEach(path -> {
                    try {
                        String content = Files.readString(path, StandardCharsets.UTF_8);

                        if (path.toString().endsWith(".kt")) {
                            processKotlinContent(content, path);
                        } else {
                            processXmlContent(content);
                        }

                    } catch (IOException e) {
                        System.err.println("读取文件失败: " + path);
                    }
                });
    }

    // 处理Kotlin后缀.kt的文件内容（关键正则表达式）
    private static void processKotlinContent(String content, Path path) {
        // 去除单行注释和多行注释的正则表达式
        final Pattern COMMENT_PATTERN = Pattern.compile(
                "//.*?$|/\\*.*?\\*/", Pattern.MULTILINE | Pattern.DOTALL
        );
        // 匹配双引号字符串的正则表达式，下面处理支持转义和模板表达式
        final Pattern CHINESE_PATTERN = Pattern.compile("\"([^\"\\r\\n]+)\"");

        // 第一步：去除所有注释
        String withoutComments = COMMENT_PATTERN.matcher(content).replaceAll("");
        // 第二步：匹配双引号字符串
        Matcher matcher = CHINESE_PATTERN.matcher(withoutComments);

        while (matcher.find()) {
            String rawString = matcher.group(1)
                    .replace("\\\"", "\"");  // 处理转义双引号

            // 提取纯中文部分
            Matcher chineseMatcher = Pattern.compile("[\\u4e00-\\u9fa5]+").matcher(rawString);
            boolean found = false;
            while (chineseMatcher.find()) {
                if (!found) {
                    modifiedFiles.add(path);  // 标记.kt文件已修改
                    found = true;
                }
                String chinese = chineseMatcher.group();
                if (!contentToKeyMap.containsKey(chinese)) {//其实这里用containsValue来判断行，因为key和value都是唯一的
                    String key = "string" + keyCounter++;
                    contentToKeyMap.put(chinese, key);
                }
            }
        }
    }

    // 处理XML文件内容
    private static void processXmlContent(String content) {
        Pattern pattern = Pattern.compile("\"((?:\\\\\"|[^\"\\r\\n])*?[\u4E00-\u9FA5]+(?:\\\\\"|[^\"\\r\\n])*?)\"");
        Matcher matcher = pattern.matcher(content);

        while (matcher.find()) {
            String rawContent = matcher.group(1)
                    .replace("\\\"", "\"");

            if (!contentToKeyMap.containsKey(rawContent)) {
                String key = "string" + keyCounter++;
                contentToKeyMap.put(rawContent, key);
            }
        }
    }

    // 第二阶段：执行实际替换
    private static void replaceAllStrings(Path root) throws IOException {
        Files.walk(root)
                .filter(Files::isRegularFile)
                .filter(p -> {
                    String fileName = p.toString().toLowerCase();
                    return fileName.endsWith(".xml") || fileName.endsWith(".kt");
                })
                .filter(p -> !p.getFileName().toString().equalsIgnoreCase("string.xml"))
                .forEach(path -> {
                    try {
                        String content = Files.readString(path, StandardCharsets.UTF_8);
                        String modifiedContent;

                        if (path.toString().endsWith(".kt")) {
                            modifiedContent = replaceKotlinContent(content);
                        } else {
                            modifiedContent = replaceXmlContent(content);
                        }

                        Files.write(path, modifiedContent.getBytes(StandardCharsets.UTF_8));
                        System.out.println("已更新文件: " + path);

                    } catch (IOException e) {
                        System.err.println("处理文件失败: " + path);
                    }
                });
    }

    // Kotlin文件替换逻辑
    private static String replaceKotlinContent(String content) {
        // 匹配双引号字符串，支持转义和模板表达式
        Pattern stringPattern = Pattern.compile("\"([^\"\\r\\n]+)\"");
        Matcher matcher = stringPattern.matcher(content);

        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            String rawString = matcher.group(1);

            // 处理纯中文部分
            String replacedContent = processQuotedString(rawString);     // 处理中文字符串

            // 关键转义处理
            String replacement = Matcher.quoteReplacement("\"" + replacedContent + "\"");

            matcher.appendReplacement(sb, replacement);
        }

        matcher.appendTail(sb);

        return sb.toString();
    }

    private static String processQuotedString(String quotedContent) {
        // 按出现位置逆序处理
        List<String> chineseList = new ArrayList<>();
        Matcher chineseMatcher = Pattern.compile("[\\u4e00-\\u9fa5]+").matcher(quotedContent);
        while (chineseMatcher.find()) {
            chineseList.add(chineseMatcher.group());
        }

        // 从后往前替换避免偏移
        String result = quotedContent;
        for (int i = chineseList.size() - 1; i >= 0; i--) {
            String chinese = chineseList.get(i);
            String key = contentToKeyMap.get(chinese);
            if (key != null) {
                // 构造替换表达式
                String replacement = "${stringById(R.string." + key + ")}";
                result = result.replace(chinese, replacement);
            }
        }
        return result;
    }


    // XML文件替换逻辑
    private static String replaceXmlContent(String content) {
        Pattern pattern = Pattern.compile("\"((?:\\\\\"|[^\"\\r\\n])*?[\u4E00-\u9FA5]+(?:\\\\\"|[^\"\\r\\n])*?)\"");
        Matcher matcher = pattern.matcher(content);

        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            String rawContent = matcher.group(1)
                    .replace("\\\"", "\"");
            String key = contentToKeyMap.get(rawContent);
            matcher.appendReplacement(sb, "\"@string/" + key + "\"");
        }
        matcher.appendTail(sb);

        return sb.toString();
    }

    // 第三阶段：为修改过的文件插入导入语句
    private static void insertImportsForModifiedFiles() throws IOException {
        for (Path path : modifiedFiles) {
            List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
            insertImports(lines);
            Files.write(path, lines, StandardCharsets.UTF_8);
            System.out.println("已更新导入: " + path);
        }
    }

    // 插入导入语句到第三行
    private static void insertImports(List<String> lines) {
        boolean hasR = lines.contains(IMPORT_R);
        boolean hasStringById = lines.contains(IMPORT_STRING_BY_ID);

        if (hasR && hasStringById) return;

        int insertPosition = 2; // 默认第二行

        // 查找第一个package声明所在的行
        int packageLine = -1;
        for (int i = 0; i < lines.size(); i++) {
            if (lines.get(i).startsWith("package")) {
                packageLine = i;
                break;
            }
        }
        // 设置插入位置
        if (packageLine != -1) {
            // 找到package声明，在package行后面两行插入
            insertPosition = packageLine + 2;
        }

        // 防止索引越界
        insertPosition = Math.min(insertPosition, lines.size());

        // 插入R导入
        if (!hasR) {
            lines.add(insertPosition, IMPORT_R);
            insertPosition++;
        }
        // 插入stringById导入
        if (!hasStringById) {
            lines.add(insertPosition, IMPORT_STRING_BY_ID);
        }
    }
}